#include "appupgrade_plugin.h"

// This must be included before many other Windows headers.
#include <windows.h>

// For getPlatformVersion; remove unless needed for your plugin implementation.
#include <VersionHelpers.h>

#include <flutter/method_channel.h>
#include <flutter/plugin_registrar_windows.h>
#include <flutter/standard_method_codec.h>

#include <memory>
#include <sstream>

using namespace std;

namespace appupgrade {

struct _LANGCODEPAGE {
    int wLanguage;
    int wCodePage;
};

class AutoUpdate {
    private:
    static wchar_t* strtowstr(const std::string &str)
    {
        // Convert an ASCII string to a Unicode String
        wchar_t *wszTo = new wchar_t[str.length() + 1];
        wszTo[str.size()] = L'\0';
        MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, wszTo, (int)str.length());
        return wszTo;
    }
    static string wstrtostr(const wstring &wstr)
    {
        // Convert a Unicode string to an ASCII string
        string strTo;
        char *szTo = new char[wstr.length() + 1];
        szTo[wstr.size()] = '\0';
        WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, szTo, (int)wstr.length(), NULL, NULL);
        strTo = szTo;
        delete[] szTo;
        return strTo;
    }
    public:
    //static string getDownloadFolder(){
        //return AutoUpdate::getKnownFolder(FOLDERID_Downloads);
   // }
   // static string getDocumentsFolder(){
       // return AutoUpdate::getKnownFolder(FOLDERID_Documents);
    //}
    static HINSTANCE runFileWindows(string filePath){
        string path = filePath.substr(0, filePath.rfind("\\"));
        wchar_t* lpFile = AutoUpdate::strtowstr(filePath);
        wchar_t* lpDirectory = AutoUpdate::strtowstr(path);

        HINSTANCE hins = ShellExecuteW(NULL, L"open", lpFile, NULL, lpDirectory, 0);

        delete[] lpFile;
        delete[] lpDirectory;

        return hins;
    }
};

// static
void AppupgradePlugin::RegisterWithRegistrar(
    flutter::PluginRegistrarWindows *registrar) {
  auto channel =
      std::make_unique<flutter::MethodChannel<flutter::EncodableValue>>(
          registrar->messenger(), "appupgrade",
          &flutter::StandardMethodCodec::GetInstance());

  auto plugin = std::make_unique<AppupgradePlugin>();

  channel->SetMethodCallHandler(
      [plugin_pointer = plugin.get()](const auto &call, auto result) {
        plugin_pointer->HandleMethodCall(call, std::move(result));
      });

  registrar->AddPlugin(std::move(plugin));
}

AppupgradePlugin::AppupgradePlugin() {}

AppupgradePlugin::~AppupgradePlugin() {}

void AppupgradePlugin::HandleMethodCall(
    const flutter::MethodCall<flutter::EncodableValue> &method_call,
    std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
   if (method_call.method_name().compare("executeUpdater") == 0) {
       auto *arguments = std::get_if<flutter::EncodableMap>(method_call.arguments());
       auto filePath = std::get<std::string>(arguments->at(flutter::EncodableValue("path")));
       int64_t res = (int64_t) AutoUpdate::runFileWindows(filePath);
        result->Success(flutter::EncodableValue(res));
   }
  else {
    result->NotImplemented();
  }
}

}  // namespace appupgrade
